package pure.engine.idea 
{
	import pure.debug.Logger;
	import pure.engine.Multiple;
	
	/**
	 * 反应组合
	 * [Author] - PURE
	 * 
	 */
final internal class ReactionCombo implements IReactionCombo
{
	public function ReactionCombo(reactor:Reactor)
	{
		m_reactor = reactor;
	}

	
	
	
	
	//======================
	// base
	//======================
	

	/**
	 * 加入
	 * 
	 * [Hint] - 只有一个项目时，首尾为同一个
	 * 
	 * [Param] - item  反应项目
	 * [Param] - vars  属性参数
	 */
	public function push(item:ReactionItem, vars:Object = null, needBreakOff:Boolean = false):void
	{
		_breakOff(needBreakOff);
		item.setProperty(vars);
		if (!m_first)
		{
			m_first = m_last = item;
		}
		else
		{
			item.prev = m_last;
			m_last = m_last.next = item;
		}
	}
	
	
	/**
	 * 开始
	 */
	public function start():void
	{
		if (!m_first)
		{
			Logger.reportError(this, 'start', '反应队列中没有项目');
		}
		
		m_delay          =  m_first.delay;
		m_onStart        =  m_first.onStart;
		m_onStartParams  =  m_first.onStartParams;
		m_onEnd          =  m_first.onEnd;
		m_onEndParams    =  m_first.onEndParams;
		
		_doDelay();
	}

	
	/**
	 * 结束
	 */
	public function stop():void
	{	
		_breakOff(true);
	}

	
	

	
	
	/* ----------------------------------------------------------------------------------------------------------------
	 * ★★★★★★★★★★★★★★★★★★★★★  private  ★★★★★★★★★★★★★★★★★★★★★
	 * ----------------------------------------------------------------------------------------------------------------
	 */
	
	
	
	
	/**
	 * 延迟
	 */
	protected function _doDelay():void
	{
		if (m_delay > 0)
		{
			m_uid = Multiple.delay.delayedCall(m_delay, _doStart);
		}
		else
		{
			_doStart();
		}
	}
	
	
	/**
	 * 开始
	 */
	protected function _doStart():void
	{
		var t:Number = m_first.execute(m_reactor)
		
		if (m_onStart != null)
		{
			m_onStart.apply(null, m_onStartParams);
		}
		m_uid = Multiple.delay.delayedCall(t, _doEnd);
	}
	
	
	/**
	 * 结束
	 */
	protected function _doEnd():void
	{
		if (m_onEnd != null)
		{
			m_onEnd.apply(null, m_onEndParams);
		}
		_doNext();
	}
	
	
	/**
	 * 继续
	 */
	protected function _doNext():void
	{
		if(m_first.next)
		{
			var Q:ReactionItem = m_first;
			
			m_first.next.prev  =  null;
			m_first            =  m_first.next;
			m_delay            =  m_first.delay;
			m_onStart          =  m_first.onStart;
			m_onStartParams    =  m_first.onStartParams;
			m_onEnd            =  m_first.onEnd;
			m_onEndParams      =  m_first.onEndParams;
			
			Q.dispose();
			_doDelay();
		}
		else
		{
			m_first          =  m_last         =  null;
			m_onStart        =  m_onEnd        =  null;
			m_onStartParams  =  m_onEndParams  =  null;
			m_uid = -1;
		}
	}
	
	
	/**
	 * 中断
	 * 
	 * [Param] - entirely  完全中断，移除队列其他项目
	 */
	protected function _breakOff(entirely:Boolean):void
	{
		if (m_uid != -1)
		{
			Multiple.delay.removeDelayedCall(m_uid);
			m_uid = -1;
		}
		
		if (entirely)
		{
			while (m_first)
			{
				m_first.dispose();
				if(m_first.next)
				{
					m_first.next.prev = null;
					m_first = m_first.next;
				}
				else
				{
					m_first = m_last = null;
				}
			}
			m_onStart        =  m_onEnd        =  null;
			m_onStartParams  =  m_onEndParams  =  null;
		}
	}
	
	
	/**
	 * 获取
	 */
	internal static function getInstance(reactor:Reactor):ReactionCombo
	{
		if (numCombo > 0)
		{
			--numCombo;
			return cachedCombo.pop();
		}
		return new ReactionCombo(reactor);
	}
	
	
	/**
	 * 回收
	 */
	internal function recycle():void
	{
		_breakOff(true);
		m_reactor = null;
		cachedCombo[numCombo++] = this;
	}
	
	
	
	
	
	
	//======================
	// Member
	//======================
	
	
	protected static var cachedCombo:Vector.<ReactionCombo> = new Vector.<ReactionCombo>();
	
	protected static var numCombo:int;
	
	
	protected var m_reactor:Reactor;  // 反应器
	
	protected var m_uid:int = -1;  //  -1代表没有延迟方法
	
	protected var m_first:ReactionItem, m_last:ReactionItem;

	protected var m_delay:Number;
	
	protected var m_onStart:Function, m_onEnd:Function;
	
	protected var m_onStartParams:Array, m_onEndParams:Array;


	
}

}